import router from '@/router'
import { useLoginStore } from '@/stores'
import type { AxiosInstance, AxiosRequestConfig, Method } from 'axios'
import axios from 'axios'
import { ElMessage } from 'element-plus'

type Data<T> = {
  msg: string
  code: number
  data: T
}

class Request {
  instance: AxiosInstance

  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config)
    // 请求拦截器
    this.instance.interceptors.request.use(
      async (config) => {
        // 修改config, 比如:修改请求头
        const store = useLoginStore()
        if (store.token && config.headers) {
          config.headers.Authorization = `Bearer ${store.token}`
        }
        return config
      },
      (err) => Promise.reject(err)
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (res) => {
        if (res.data?.code !== 0) {
          ElMessage({
            message: res.data.msg || '网络错误',
            type: 'error'
          })

          if (res.data.code === 401) {
            const loginStore = useLoginStore()
            loginStore.delToken()
            router.push(`/login?returnUrl=${router.currentRoute.value.fullPath}`)
          }
          return Promise.reject(res.data)
        }
        return res.data
      },
      () => {
        ElMessage({
          message: '网络错误',
          type: 'error'
        })
        return Promise.reject('网络错误')
      }
    )
  }

  request<T>(url: string, method: Method = 'get', submitData?: object, params?: object) {
    return this.instance.request<T, Data<T>>({
      url,
      method,
      data: submitData,
      params
    })
  }

  get<T>(url: string, submitData?: object) {
    return this.instance.request<T, Data<T>>({
      url,
      method: 'GET',
      params: submitData
    })
  }

  post<T>(url: string, submitData?: object, params?: Object) {
    return this.request<T>(url, 'POST', submitData, params)
  }

  delete<T>(url: string, submitData?: object) {
    return this.request<T>(url, 'DELETE', submitData)
  }

  put<T>(url: string, submitData?: object) {
    return this.request<T>(url, 'PUT', submitData)
  }
}

export default Request
